/*
 * @Author: wwssaabb
 * @Date: 2021-09-04 08:14:46
 * @LastEditTime: 2021-12-13 09:02:17
 * @FilePath: \handwritten-code\main\apply.js
 */
/* 
  和call的区别为传参不一样，apply第二个参数必须为一个参数数组
  call没有传参限制
  思路：新增属性添加到apply要绑定的对象上，为避免属性名覆盖使用Symbol
      创建属性名，这个属性存储的是this，也就是调用apply的函数，然后在
      context对象上调用这个属性的函数（记得传参），获取结果之后删除context
      新添加的属性，返回结果。
  原理：使用隐式绑定将this绑定到指定对象
  */

Function.prototype.my_apply = function (context = global, args) {
  if (!Array.isArray(args)) {
    throw new TypeError('type error')
  }
  //除了参数处理不一样，大致上和call一样
  const key = Symbol('key')
  context[key] = this
  const res = context[key](args)
  delete context[key]
  return res
}

const p1 = {
  name: '张三',
  age: 20,
  say: function (name, age) {
    console.log(`我是${name}，今年${age}岁`)
  }
}

const p2 = {
  name: '李四',
  age: 18,
}

p1.say.my_apply(p2, [...Object.values(p2)])
// p1.say.my_apply(p2,'李四',18)
